package de.IIIfeed.MoneyPlanner;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MoneyPlan {
	List<Item> items;
	float initialAmount;
	Date initialDate;
	
	/**
	 * @param items
	 * @param initialAmount
	 */
	public MoneyPlan(List<Item> items, float initialAmount, Date initialTime) {
		super();
		this.items = items;
		this.initialAmount = initialAmount;
		this.initialDate = initialTime;
	}
	
	/**
	 * find the last amount before d
	 * @param d
	 * @return 
	 */
	public float getAmountAt(Date d){
		if(items.size() == 0){
			return initialAmount;
		}
		Map<Date, Float> amounts = getAmountsUntil(d);
		if(amounts.containsKey(d)){
			return amounts.get(d);
		} else {
			//find the last before d 
			Date last = new Date(0);
			for(Date i : amounts.keySet()){
				if(i.before(d) && i.after(last)){
					last = i;
				}
			}
			return amounts.get(last);
		}
	}
	
	protected Map<Date, Float> getAmountsUntil(Date d){
		Map<Date, Float> amounts = new HashMap<Date, Float>();
		
		//get relevant items
		ArrayList<Item> items = getItemsUntil(d);
		//expand the periodical items
		ArrayList<Item> expanded = expandPeriodicalItems(items, d);
		//sort them
		Collections.sort(expanded);
		
		amounts.put(initialDate, initialAmount);
		
		//sum all items
		float sum = initialAmount;
		for(Item item : expanded){
			sum += item.amount;
			amounts.put(item.dateStart, sum);
		}
		return amounts;
	}
	
	protected ArrayList<Item> expandPeriodicalItems(ArrayList<Item> items, Date until){
		ArrayList<Item> expandedItems = new ArrayList<Item>();
		for(Item item : items){
			if(item.type == MoneyPlanner.PERIODICALLY){
				for(int i = 0; i < getNumOccurencesUntil(item, until); i++){
					expandedItems.add(
						//make a copy that is not periodically for every implicit item
						new Item(0, item.title, item.amount, MoneyPlanner.ONCE, new Timestamp(item.dateStart.getTime() + (i * item.repeatType)), 0, 0, 0, null)
					);
				}
			} else {
				expandedItems.add(item);
			}
		}

		return expandedItems;
	}
	
	protected ArrayList<Item> getItemsUntil(Date d){
		ArrayList<Item> before = new ArrayList<Item>();
		for(Item i : items){
			if(i.dateStart.before(d)){
				before.add(i);
			}
		}
		return before;
	}
	
	protected long getNumOccurencesUntil(Item i, Date d){
		if(d.before(i.dateStart)){
			return 0;
		}
		if(i.type == MoneyPlanner.ONCE){
			return 1;
		} else {
			//calc periodical items
			long diffMs = d.getTime() - i.dateStart.getTime();
			
			if (i.repeatType == MoneyPlanner.DAILY)
				return (diffMs / MoneyPlanner.DAILY);
			else if (i.repeatType == MoneyPlanner.MONTHLY)
				return (diffMs / MoneyPlanner.MONTHLY);
			else if (i.repeatType == MoneyPlanner.WEEKLY)
				return (diffMs / MoneyPlanner.WEEKLY);
			else if (i.repeatType == MoneyPlanner.YEARLY)
				return (diffMs / MoneyPlanner.YEARLY);
			
			//should not happen
			return 0;
			
		}
	}
}
